package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"
)

// 颜色定义
const (
	ColorRed    = "\033[31m"
	ColorGreen  = "\033[32m"
	ColorYellow = "\033[33m"
	ColorBlue   = "\033[34m"
	ColorReset  = "\033[0m"
)

// 打印带颜色的文本
func printColor(color, text string) {
	fmt.Printf("%s%s%s\n", color, text, ColorReset)
}

// 检查命令是否存在
func commandExists(cmd string) bool {
	_, err := exec.LookPath(cmd)
	return err == nil
}

// 执行命令并返回结果
func runCommand(cmd string, args ...string) error {
	command := exec.Command(cmd, args...)
	command.Stdout = os.Stdout
	command.Stderr = os.Stderr
	return command.Run()
}

// 执行命令并获取输出
func runCommandWithOutput(cmd string, args ...string) (string, error) {
	command := exec.Command(cmd, args...)
	output, err := command.Output()
	return string(output), err
}

// 等待用户输入
func waitForInput(prompt string) string {
	fmt.Print(prompt)
	reader := bufio.NewReader(os.Stdin)
	input, _ := reader.ReadString('\n')
	return strings.TrimSpace(input)
}

// 等待服务启动
func waitForService(serviceName string, checkFunc func() bool, maxAttempts int) bool {
	printColor(ColorBlue, fmt.Sprintf("检查%s服务状态...", serviceName))
	
	for i := 1; i <= maxAttempts; i++ {
		if checkFunc() {
			printColor(ColorGreen, fmt.Sprintf("%s服务运行正常", serviceName))
			return true
		}
		
		if i < maxAttempts {
			printColor(ColorYellow, fmt.Sprintf("%s服务可能还在启动中，请稍等... (%d/%d)", serviceName, i, maxAttempts))
			time.Sleep(2 * time.Second)
		}
	}
	
	printColor(ColorRed, fmt.Sprintf("%s服务启动失败", serviceName))
	return false
}

// 检查MySQL服务
func checkMySQL() bool {
	_, err := runCommandWithOutput("docker", "exec", "sysu-giep-mysql", "mysqladmin", "ping", "-h", "localhost", "--silent")
	return err == nil
}

// 检查Redis服务
func checkRedis() bool {
	_, err := runCommandWithOutput("docker", "exec", "sysu-giep-redis", "redis-cli", "ping")
	return err == nil
}

// 检查应用服务
func checkApp() bool {
	_, err := runCommandWithOutput("curl", "-s", "http://localhost:8080/api/v1/health")
	return err == nil
}

// 启动数据库服务
func startDatabaseServices() error {
	printColor(ColorBlue, "启动数据库服务...")
	return runCommand("docker-compose", "up", "-d", "mysql", "redis")
}

// 启动完整环境
func startFullEnvironment() error {
	printColor(ColorBlue, "启动完整环境...")
	return runCommand("docker-compose", "up", "-d")
}

// 清理并重新构建
func cleanAndRebuild() error {
	printColor(ColorBlue, "停止并删除所有容器和卷...")
	if err := runCommand("docker-compose", "down", "-v"); err != nil {
		return err
	}
	
	if err := runCommand("docker", "system", "prune", "-f"); err != nil {
		return err
	}
	
	printColor(ColorBlue, "重新构建环境...")
	return runCommand("docker-compose", "up", "-d", "--build")
}

// 初始化数据库
func initDatabase() error {
	printColor(ColorBlue, "初始化数据库结构...")
	
	if !commandExists("go") {
		printColor(ColorYellow, "Go环境未找到，跳过数据库迁移")
		printColor(ColorYellow, "请手动运行: go run cmd/server/main.go")
		return nil
	}
	
	// 设置环境变量
	os.Setenv("DATABASE_URL", "mysql://root:password@localhost:3306/sysu_giep?charset=utf8mb4&parseTime=True&loc=Local")
	
	printColor(ColorBlue, "运行数据库迁移...")
	
	// 启动应用进行数据库迁移
	cmd := exec.Command("go", "run", "cmd/server/main.go")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	
	if err := cmd.Start(); err != nil {
		return err
	}
	
	// 等待应用启动
	time.Sleep(5 * time.Second)
	
	// 检查应用是否启动成功
	if waitForService("应用", checkApp, 10) {
		printColor(ColorGreen, "应用启动成功，数据库迁移完成")
	}
	
	// 停止应用进程
	cmd.Process.Kill()
	
	return nil
}

// 显示信息
func showInfo() {
	fmt.Println()
	printColor(ColorGreen, "========================================")
	printColor(ColorGreen, "        数据库构建完成！")
	printColor(ColorGreen, "========================================")
	fmt.Println()
	
	printColor(ColorBlue, "服务信息:")
	fmt.Println("MySQL:     localhost:3306")
	fmt.Println("Redis:     localhost:6379")
	fmt.Println("数据库名:   sysu_giep")
	fmt.Println("用户名:     root")
	fmt.Println("密码:       password")
	fmt.Println()
	
	printColor(ColorBlue, "管理命令:")
	fmt.Println("查看日志:   docker-compose logs -f mysql")
	fmt.Println("进入MySQL: docker exec -it sysu-giep-mysql mysql -u root -p")
	fmt.Println("进入Redis: docker exec -it sysu-giep-redis redis-cli")
	fmt.Println("停止服务:   docker-compose down")
	fmt.Println("重启服务:   docker-compose restart")
	fmt.Println()
	
	printColor(ColorBlue, "下一步:")
	fmt.Println("1. 运行应用: go run cmd/server/main.go")
	fmt.Println("2. 访问API: http://localhost:8080/api/v1/health")
	fmt.Println("3. 查看文档: http://localhost:8080/swagger/index.html")
	fmt.Println()
	
	// 询问是否启动应用
	startApp := waitForInput("是否现在启动应用? (y/N): ")
	if strings.ToLower(startApp) == "y" {
		printColor(ColorBlue, "启动应用服务...")
		runCommand("go", "run", "cmd/server/main.go")
	}
}

// 主函数
func main() {
	// 打印标题
	printColor(ColorBlue, "========================================")
	printColor(ColorBlue, "    中山大学研究生院校企对接平台")
	printColor(ColorBlue, "        数据库一键构建脚本")
	printColor(ColorBlue, "========================================")
	fmt.Println()
	
	// 检查Docker环境
	printColor(ColorBlue, "检查Docker环境...")
	if !commandExists("docker") {
		printColor(ColorRed, "错误: Docker未安装，请先安装Docker")
		if runtime.GOOS == "windows" {
			fmt.Println("下载地址: https://www.docker.com/products/docker-desktop")
		} else {
			fmt.Println("安装指南: https://docs.docker.com/get-docker/")
		}
		os.Exit(1)
	}
	
	printColor(ColorGreen, "Docker环境检查通过")
	
	// 检查Docker Compose
	if !commandExists("docker-compose") {
		printColor(ColorRed, "错误: Docker Compose不可用")
		os.Exit(1)
	}
	
	printColor(ColorGreen, "Docker Compose检查通过")
	fmt.Println()
	
	// 选择操作
	printColor(ColorYellow, "请选择要构建的数据库类型:")
	fmt.Println("1. MySQL (推荐)")
	fmt.Println("2. PostgreSQL")
	fmt.Println("3. 仅启动数据库服务 (MySQL + Redis)")
	fmt.Println("4. 启动完整环境 (MySQL + Redis + 应用)")
	fmt.Println("5. 清理所有数据并重新构建")
	fmt.Println()
	
	choice := waitForInput("请输入选择 (1-5): ")
	
	var err error
	switch choice {
	case "1", "2":
		printColor(ColorBlue, "开始构建数据库环境...")
		err = startDatabaseServices()
	case "3":
		printColor(ColorBlue, "启动数据库服务 (MySQL + Redis)...")
		err = startDatabaseServices()
		if err == nil {
			waitForService("MySQL", checkMySQL, 30)
			waitForService("Redis", checkRedis, 10)
			showInfo()
		}
		return
	case "4":
		printColor(ColorBlue, "启动完整环境 (MySQL + Redis + 应用)...")
		err = startFullEnvironment()
		if err == nil {
			waitForService("MySQL", checkMySQL, 30)
			waitForService("Redis", checkRedis, 10)
			showInfo()
		}
		return
	case "5":
		printColor(ColorYellow, "警告: 这将删除所有数据并重新构建")
		confirm := waitForInput("确认继续? (y/N): ")
		if strings.ToLower(confirm) != "y" {
			fmt.Println("操作已取消")
			return
		}
		err = cleanAndRebuild()
		if err == nil {
			waitForService("MySQL", checkMySQL, 30)
			waitForService("Redis", checkRedis, 10)
			showInfo()
		}
		return
	default:
		printColor(ColorRed, "无效选择")
		os.Exit(1)
	}
	
	if err != nil {
		printColor(ColorRed, "操作失败")
		log.Fatal(err)
	}
	
	// 等待服务启动
	waitForService("MySQL", checkMySQL, 30)
	waitForService("Redis", checkRedis, 10)
	
	// 初始化数据库
	initDatabase()
	
	// 显示信息
	showInfo()
}
